package zdream.pmfield.test.stage.effect;

import org.junit.Before;
import org.junit.Test;

import java.util.concurrent.atomic.AtomicInteger;

import zdream.pmfield.data.foe.BStat;
import zdream.pmfield.data.foe.Foe;
import zdream.pmfield.data.foe.MoveTemplate;
import zdream.pmfield.stage.StageBuilderForTest;
import zdream.pmfield.stage.StageWrapper;
import zdream.pmfield.stage.message.ActionStartMessage;
import zdream.pmfield.stage.message.FoeAddBuffMessage;
import zdream.pmfield.stage.message.FoeReceiveDamageMessage;
import zdream.pmfield.stage.message.FoeRemoveBuffMessage;
import zdream.pmfield.stage.message.TurnStartMessage;
import zdream.pmfield.storage.FoeTemplateStorage;
import zdream.pmfield.test.utils.ResourceConstant;
import zdream.pmfield.test.utils.StageConstant;

import static org.junit.Assert.*;

/**
 * @author Zdream
 * @date 2023-12-16
 * @since 0.0.1
 */
public class SplintersBuffCase {
	FoeTemplateStorage storage;

	@Before
	public void before() {
		storage = new FoeTemplateStorage();
		storage.load();
		storage.loadMovesInResource(ResourceConstant.RES_PATH_TEST_MOVES_JSON);
	}

	@Test
	public void testSplintersEffect() {
		MoveTemplate splintersMove = storage.findMoveById(10000050, 1);
		assertEquals("肯定碎片", splintersMove.name);
		MoveTemplate normalMove = storage.findMoveById(10000015, 1);
		assertEquals("无效果", normalMove.name);

		Foe foe1 = Foe.builder(storage.findFoeById(4))
				.withLevel(30)
				.withMove(splintersMove)
				.build();
		Foe foe2 = Foe.builder(storage.findFoeById(1))
				.withLevel(30)
				.withMove(normalMove)
				.build();
		assertTrue(foe2.bStats[BStat.HP.ordinal()] > 30);

		final StageWrapper wrapper = StageBuilderForTest.builder()
				.putFoeToOneSide(foe1)
				.putFoeToAnotherSide(foe2)
				.withStorage(storage)
				.disableDistanceCheck()
				.buildWrapper();

		System.out.println("TEST 1: apply splinters");
		wrapper.printBeforeHandleMessage();
		wrapper.onDefaultActionRequest();

		wrapper.runUntil(TurnStartMessage.class, message -> message.foe.foe == foe1);
		wrapper.runUntil(ActionStartMessage.class, message -> {
			assertTrue(message.action.isForAttack());
			assertEquals(foe1, message.action.asAttack().foe.foe);
			assertEquals(splintersMove, message.action.asAttack().move.move);
			return true;
		});
		wrapper.runUntil(FoeAddBuffMessage.class, message -> {
			assertTrue(message.success);
			assertEquals(foe2, message.foe.foe);
			assertTrue(message.buff.is(StageConstant.BUFF_SPLINTERS));
			return true;
		});

		AtomicInteger turnCount = new AtomicInteger(0);
		AtomicInteger damageCount = new AtomicInteger(0);

		System.out.println("TEST 2: splinters 状态: 每轮开始时掉血");
		wrapper.runUntil(TurnStartMessage.class, message -> {
			if (message.foe.foe == foe2) {
				turnCount.incrementAndGet();
				return true;
			}
			return false;
		});
		wrapper.runUntil(ActionStartMessage.class, message -> {
			assertTrue(message.action.isForBuff());
			assertTrue(message.action.asBuff().buff.is(StageConstant.BUFF_SPLINTERS));
			damageCount.incrementAndGet();
			return true;
		});
		wrapper.runUntil(FoeReceiveDamageMessage.class, message -> {
			assertEquals(foe2, message.foe.foe);
			return true;
		});

		System.out.println("TEST 3: splinters 状态会随时间消失");
		wrapper.clearOnMessageHooks();
		wrapper.onDefaultActionRequest();
		wrapper.onMessage(TurnStartMessage.class, message -> {
			if (message.foe.foe == foe2) {
				turnCount.incrementAndGet();
			}
		});
		wrapper.onMessage(ActionStartMessage.class, message -> {
			if (message.action.isForBuff() && message.action.asBuff().buff.is(StageConstant.BUFF_SPLINTERS)) {
				damageCount.incrementAndGet();
			}
		});

		wrapper.runUntil(FoeRemoveBuffMessage.class, message -> {
			assertEquals(message.foe.foe, foe2);
			assertTrue(message.buff.is(StageConstant.BUFF_SPLINTERS));
			return true;
		});
		assertTrue(turnCount.get() >= 3);
		assertEquals(turnCount.get(), damageCount.get() + 1);
	}
}
